package config

import (
	"fmt"
	"os"

	"github.com/BurntSushi/toml"
)

type Config struct {
	// Root directory for snapshotter data
	Root string `toml:"root"`

	// Cache configuration
	Cache CacheConfig `toml:"cache"`

	// Registry configuration
	Registry RegistryConfig `toml:"registry"`

	// Download configuration
	Download DownloadConfig `toml:"download"`

	// Deduplication configuration (V2.0)
	Dedup DedupConfig `toml:"dedup"`

	// Ublk configuration (V2.0)
	Ublk UblkConfig `toml:"ublk"`

	// Prefetch configuration (V2.0)
	Prefetch PrefetchConfig `toml:"prefetch"`

	// Monitoring configuration (V2.0)
	Metrics MetricsConfig `toml:"metrics"`
}

type CacheConfig struct {
	// Maximum cache size in bytes
	MaxSize int64 `toml:"max_size"`

	// Cache directory
	Dir string `toml:"dir"`

	// Hot cache size (memory/tmpfs)
	HotCacheSize int64 `toml:"hot_cache_size"`

	// Enable write-back cache
	WriteBack bool `toml:"write_back"`
}

type RegistryConfig struct {
	// Default registry host
	Host string `toml:"host"`

	// Skip TLS verification
	Insecure bool `toml:"insecure"`

	// Registry mirrors
	Mirrors []string `toml:"mirrors"`
}

type DownloadConfig struct {
	// Maximum concurrent downloads
	Concurrency int `toml:"concurrency"`

	// Download timeout in seconds
	Timeout int `toml:"timeout"`

	// Retry attempts
	MaxRetries int `toml:"max_retries"`

	// Download buffer size
	BufferSize int `toml:"buffer_size"`
}

type DedupConfig struct {
	// Enable deduplication
	Enabled bool `toml:"enabled"`

	// Chunk size in bytes (default 4MB)
	ChunkSize int64 `toml:"chunk_size"`

	// Chunking algorithm: "fixed" or "cdc"
	Algorithm string `toml:"algorithm"`

	// Content store directory
	StoreDir string `toml:"store_dir"`

	// Enable compression for chunks
	Compression bool `toml:"compression"`
}

type UblkConfig struct {
	// Enable ublk driver
	Enabled bool `toml:"enabled"`

	// Number of queues
	NumQueues int `toml:"num_queues"`

	// Queue depth
	QueueDepth int `toml:"queue_depth"`

	// Fallback to FUSE if ublk unavailable
	FallbackToFuse bool `toml:"fallback_to_fuse"`
}

type PrefetchConfig struct {
	// Enable prefetch
	Enabled bool `toml:"enabled"`

	// Maximum files to prefetch
	MaxFiles int `toml:"max_files"`

	// Prefetch concurrency
	Concurrency int `toml:"concurrency"`

	// Prefetch on snapshot prepare
	OnPrepare bool `toml:"on_prepare"`
}

type MetricsConfig struct {
	// Enable metrics collection
	Enabled bool `toml:"enabled"`

	// Metrics collection interval in seconds
	Interval int `toml:"interval"`
}

func Load(path string) (*Config, error) {
	cfg := &Config{
		Root: "/var/lib/onyx",
		Cache: CacheConfig{
			MaxSize:      10 * 1024 * 1024 * 1024, // 10GB
			Dir:          "/var/lib/onyx/cache",
			HotCacheSize: 1 * 1024 * 1024 * 1024, // 1GB
			WriteBack:    false,
		},
		Registry: RegistryConfig{
			Host:     "registry-1.docker.io",
			Insecure: false,
			Mirrors:  []string{},
		},
		Download: DownloadConfig{
			Concurrency: 5,
			Timeout:     300,
			MaxRetries:  3,
			BufferSize:  32 * 1024, // 32KB
		},
		Dedup: DedupConfig{
			Enabled:     true,
			ChunkSize:   4 * 1024 * 1024, // 4MB
			Algorithm:   "fixed",
			StoreDir:    "/var/lib/onyx/chunks",
			Compression: false,
		},
		Ublk: UblkConfig{
			Enabled:        false, // Disabled by default (needs kernel 6.0+)
			NumQueues:      4,
			QueueDepth:     128,
			FallbackToFuse: false,
		},
		Prefetch: PrefetchConfig{
			Enabled:     true,
			MaxFiles:    50,
			Concurrency: 3,
			OnPrepare:   true,
		},
		Metrics: MetricsConfig{
			Enabled:  true,
			Interval: 10,
		},
	}

	// Try to load config file
	if _, err := os.Stat(path); err == nil {
		if _, err := toml.DecodeFile(path, cfg); err != nil {
			return nil, fmt.Errorf("failed to decode config: %w", err)
		}
	}

	// Validate configuration
	if err := cfg.Validate(); err != nil {
		return nil, fmt.Errorf("invalid configuration: %w", err)
	}

	return cfg, nil
}

func (c *Config) Validate() error {
	if c.Root == "" {
		return fmt.Errorf("root directory cannot be empty")
	}

	if c.Cache.MaxSize <= 0 {
		return fmt.Errorf("cache max_size must be positive")
	}

	if c.Download.Concurrency <= 0 {
		return fmt.Errorf("download concurrency must be positive")
	}

	if c.Dedup.Enabled {
		if c.Dedup.ChunkSize <= 0 {
			return fmt.Errorf("dedup chunk_size must be positive")
		}
		if c.Dedup.Algorithm != "fixed" && c.Dedup.Algorithm != "cdc" {
			return fmt.Errorf("dedup algorithm must be 'fixed' or 'cdc'")
		}
	}

	if c.Ublk.Enabled {
		if c.Ublk.NumQueues <= 0 {
			return fmt.Errorf("ublk num_queues must be positive")
		}
		if c.Ublk.QueueDepth <= 0 {
			return fmt.Errorf("ublk queue_depth must be positive")
		}
	}

	return nil
}
